#ifndef	INCLUDE_AH_MIND_IMPL_H
#define INCLUDE_AH_MIND_IMPL_H

/*#########################################################################*/
/*#########################################################################*/

#include <platform/include/ah_platform.h>

class MindActiveMemoryObject;
class MindSensorSetTracker;
class CortexSpatialPoolerItem;
class CortexSpatialPooler;
class CortexTemporalPoolerItem;
class CortexTemporalPooler;
class AllocortexRegion;
class NeocortexRegion;
class NucleiRegion;
class NerveRegion;
class MindRegionCreateInfo;
class ExcitatoryLink;
class InhibitoryLink;
class ModulatoryLink;

/*#########################################################################*/
/*#########################################################################*/

class NeuroLink;
class NeuroSignal;
class NeuroSignalSet;
class MindSensorSet;

/*#########################################################################*/
/*#########################################################################*/

extern neurovt_state	NEURON_SYNAPTIC_THRESHOLD_INITIAL_pQ;				// default level after which action potential reaches soma membrane
extern neurovt_state	NEURON_SYNAPTIC_THRESHOLD_MIN_pQ;					// minimum level of membrane potential threshold
extern neurovt_state	NEURON_ACTION_POTENTIAL_BY_SIGNAL_pQ;				// increase in accumulated potential generated by signal
extern neurovt_state	NEURON_MEMBRANE_POTENTIAL_BY_ACTION_POTENTIAL_pQ;	// increase in membrane potential generated by action potential
extern neurovt_state	NEURON_MEMBRANE_THRESHOLD_INITIAL_pQ;				// level after which membrane potential produces fire event
extern neurovt_state	NEURON_FIRE_OUTPUT_BY_MEMBRANE_POTENTIAL_pQ;		// increase in fire state generated by membrane potential
extern neurovt_state	NEURON_INHIBIT_DELAY_ms;							// silent period after receiving inhibitory signal
extern neurovt_state	NEURON_FIRE_OUTPUT_SILENT_ms;						// silent period after fire event
extern neurovt_state	NEURON_FIRE_IMPULSE_pQ;								// action potential amount
extern neurovt_state	NEURON_POTENTIAL_DISCHARGE_RATE_pQ_per_ms;			// action potential dischange rate
extern neurovt_state	NEURON_OUTPUT_DISCHARGE_RATE_pQ_per_ms;				// membrane potential dischange rate
extern int				NEURON_CONNECTIVITY_UPDATE_FACTOR;					// when neuron is not fired, connectivity is increased by reduction of threshold
extern RFC_INT64		NEURON_FULL_RELAX_ms;								// period of guaranteed full dischange disregarding initial potential

/*#########################################################################*/
/*#########################################################################*/

class MindActiveMemoryObject : public ThreadPoolTask {
public:
	MindActiveMemoryObject( int id );
	~MindActiveMemoryObject();
	virtual const char *getClass() { return( "MindActiveMemoryObject" ); };

	void setTargetItem( NeuroLink *link );
	void execute();
	bool needExecution();
	bool finished();

private:
	int activeMemoryObjectId;
	String name;
	NeuroLink *targetItem;
};

/*#########################################################################*/
/*#########################################################################*/

class MindSensorSetTracker : public Object {
public:
	MindSensorSetTracker( MindSensorSet *set );
	virtual const char *getClass() { return( "MindSensorSetTracker" ); };

public:
	void startTracker();
	void stopTracker();

private:
	void threadSensesTrackerMain( void *p_arg );
	void pollIteration( int& sleepRemained );

private:
	MindSensorSet *set;
	RFC_HND threadSensesTracker;
	bool runSensesTracker;
};

// #############################################################################
// #############################################################################

class CortexSpatialPoolerItem : public Object {
public:
	CortexSpatialPoolerItem();
	virtual const char *getClass() { return( "CortexSpatialPoolerItem" ); };

	int getId();
	int getUsage();
	void addUsage();
	void setId( int p_id );
	int setStateFromPool( NeuroPool *pool );
	void setStateFromSignal( NeuroSignal *signal );
	void setPoolState( NeuroPool *pool );
	void getSignalFromState( NeuroSignal *signal );
	int getDifferencePercentage( CortexSpatialPoolerItem *item , neurovt_state toleranceNeuronState );
	void logItem();
	String getBinaryState();
	String getNumberedState();

private:
	int id;
	int usage;
	FlatList<int> indexList;
};

class CortexSpatialPooler : public Object {
public:
	CortexSpatialPooler();
	virtual ~CortexSpatialPooler();
	virtual const char *getClass() { return( "CortexSpatialPooler" ); };
	
	void create( int poolSize , int sizeX , int sizeY );
	void setMatchTolerance( int tolerancePattern , int toleranceNeuronState );
	void setProtectedUsage( int usage );

	int matchPattern( NeuroSignal *signal , int *matchProbability , int *patternForgotten );
	bool getPattern( int pattern , NeuroSignal *signal );
	CortexSpatialPoolerItem *findBestMatch( CortexSpatialPoolerItem *data , int *difference );
	CortexSpatialPoolerItem *findLeastUsed();
	void logItems();

private:
	int maxPoolSize;
	int patternSizeX;
	int patternSizeY;

	int matchTolerancePattern;
	int matchToleranceNeuronState;
	int protectedUsage;

	ClassList<CortexSpatialPoolerItem> items;
};

// #############################################################################
// #############################################################################

class CortexTemporalPoolerItem : public Object {
public:
	CortexTemporalPoolerItem( int p_maxDepth );
	virtual ~CortexTemporalPoolerItem();
	virtual const char *getClass() { return( "CortexTemporalPoolerItem" ); };

	int getId();
	void setId( int p_id );
	void deleteSpatialPatternIfAny( int spatialPattern );
	void addUsage();
	int getUsage();
	void setUsage( int p_usage );
	void setData( int *data , int dataSize );
	int getDifferencePercentage( int *data , int dataSize );
	int getPartialDifferencePercentage( int *data , int dataSize );
	int getDataSize();
	int getSpatialPattern( int index );
	String getNumberedState();
	void logItem();

private:
	int id;
	int usage;
	int maxDepth;
	int *streamData;
	int streamDataSize;
};

class CortexTemporalPooler : public Object {
public:
	CortexTemporalPooler();
	virtual ~CortexTemporalPooler();
	virtual const char *getClass() { return( "CortexTemporalPooler" ); };

	void create( int poolSize , int depth );
	void setMatchTolerance( int tolerancePattern );
	void setProtectedUsage( int usage );
	void setPredictionProbabilityTolerance( int tolerance );
	void setPredictionMatchTolerance( int tolerance );
	void forgetSpatialPattern( int spatialPattern );
	int matchPattern( int spatialPattern ,  int *spatialPatternPredicted , int *predictionProbability , int *temporalPatternForgotten );
	CortexTemporalPoolerItem *matchFillPattern( int *data , int datasize , int spatialPattern , int *temporalPatternForgotten );
	int predictPattern( int *data , int datasize , int *spatialPatternPredicted , int *predictionProbability );
	CortexTemporalPoolerItem *findBestMatch( int minSize , int *data , int dataSize , int *difference , int *matchedCount );
	CortexTemporalPoolerItem *findPartialBestMatch( int minSize , int *data , int dataSize , int *difference , int *matchedCount );
	CortexTemporalPoolerItem *findLeastUsed();
	void logItems();

private:
	int maxPoolSize;
	int maxDepth;
	int protectedUsage;
	ClassList<CortexTemporalPoolerItem> items;
	int *streamData;
	int streamDataSize;
	int matchTolerancePattern;
	int predictionProbabilityTolerance;
	int predictionMatchTolerance;
};

/*#########################################################################*/
/*#########################################################################*/

class MockRegion : public MindRegion {
public:
	MockRegion( String typeName , MindArea *area );
	virtual const char *getClass() { return( "MockRegion" ); };

public:
	// MindRegion lifecycle
	virtual void createRegion( MindRegionCreateInfo *info );
	virtual void exitRegion();
	virtual void destroyRegion();

	// NeuroLink support
	virtual String getRegionType();
	virtual void getSourceSizes( String entity , int *sizeX , int *sizeY );

private:
	// neurolink handlers
	NeuroSignalSet *handleApplyNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	NeuroSignal *handleGetNeuroLinkMessage( NeuroLink *link , NeuroLinkSource *point );

private:
	// utilities
	String typeName;
	RFC_INT64 msLast;
	RFC_INT64 msLastModulation;

	// own data
	ClassList<NeuroLinkSource> sourceConnectors;
	ClassList<NeuroLinkTarget> targetConnectors;
};

/*#########################################################################*/
/*#########################################################################*/

class NeocortexRegion : public MindRegion {
public:
	NeocortexRegion( MindArea *area );
	virtual const char *getClass() { return( "NeocortexRegion" ); };

public:
	// MindRegion lifecycle
	virtual void createRegion( MindRegionCreateInfo *info );
	virtual void exitRegion();
	virtual void destroyRegion();

	// NeuroLink support
	virtual String getRegionType();
	virtual void getSourceSizes( String entity , int *sizeX , int *sizeY );

private:
	// neurolink handlers
	NeuroSignalSet *handleFeedForwardNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	NeuroSignalSet *handleFeedBackNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	// NeuroSignalSet *handleAttentionNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );

private:
// own data
	NeuroLinkSource sourceFeedForward;
	NeuroLinkSource sourceFeedBack;
	NeuroLinkTarget targetFeedForward;
	NeuroLinkTarget targetFeedBack;

	// NeuroPool layerTemporalFeedback;	// layer 2
	// NeuroPool layerSpatial;				// layer 3
	// NeuroPool layerTemporal;			// layer 4
	// NeuroPool layerAttention;			// layer 5
	// NeuroPool layerSpatialFeedback;		// layer 6

	NeuroPool inputPool;
	NeuroPool feedbackPool;
	CortexSpatialPooler *spatialPooler;
	CortexTemporalPooler *temporalPooler;

// utilities
	int sizeX;
	int sizeY;
	bool useSpatialPooler;
	bool useTemporalPooler;
	int temporalDepth;
	int spatialPatternExpected;
};

/*#########################################################################*/
/*#########################################################################*/

class AllocortexRegion : public MindRegion {
public:
	AllocortexRegion( MindArea *area );
	virtual const char *getClass() { return( "AllocortexRegion" ); };

public:
	// MindRegion lifecycle
	virtual void createRegion( MindRegionCreateInfo *info );
	virtual void exitRegion();
	virtual void destroyRegion();

	// NeuroLink support
	virtual String getRegionType();
	virtual void getSourceSizes( String entity , int *sizeX , int *sizeY );

private:
	// neurolink handlers
	void handleFeedForwardNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	// void handleFeedBackNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	// void handleAttentionNeuroLinkMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );

private:
};

// #############################################################################
// #############################################################################

class NucleiRegion : public MindRegion {
public:
	NucleiRegion( MindArea *area );
	virtual const char *getClass() { return( "NucleiRegion" ); };

public:
	// MindRegion lifecycle
	virtual void createRegion( MindRegionCreateInfo *info );
	virtual void exitRegion();
	virtual void destroyRegion();

	// NeuroLink support
	virtual String getRegionType();
	virtual void getSourceSizes( String entity , int *sizeX , int *sizeY );

private:
	// neurolink handler
	void handleSubTargetMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );
	void handleInterNeuronsTargetMessage( NeuroLink *link , NeuroLinkTarget *point , NeuroSignal *data );

private:
// own data
	NeuroLinkSource source;
	NeuroLinkTarget targetSub;
	NeuroLinkTarget targetInterNeurons;
	NeuroLink *linkInterNeuronsToSub;

	NeuroPool neuroPoolSub;
	NeuroPool neuroPoolInterNeurons;
};

/*#########################################################################*/
/*#########################################################################*/

class NerveRegion : public MindRegion {
public:
	NerveRegion( MindArea *area );
	virtual const char *getClass() { return( "NerveRegion" ); };

public:
	// MindRegion lifecycle
	virtual void createRegion( MindRegionCreateInfo *info );
	virtual void exitRegion();
	virtual void destroyRegion();

	// NeuroLink support
	virtual String getRegionType();
	virtual void getSourceSizes( String entity , int *sizeX , int *sizeY );
};

/*#########################################################################*/
/*#########################################################################*/

class MindRegionCreateInfo : public Object {
public:
MindRegionCreateInfo();
	virtual ~MindRegionCreateInfo();
	virtual const char *getClass() { return( "MindRegionCreateInfo" ); };

public:
	void setId( String id );
	void setType( MindRegionTypeDef *typeDef );

	void setSizeInfo( int nx , int ny );
	void setTemporalDepth( int nDepth );
	void setUsingSpatialPooler( bool useSpatialPooler );
	void setUsingTemporalPooler( bool useTemporalPooler );
	void setSpatialPoolerSize( int spatialPoolerSize );
	void setTemporalPoolerSize( int temporalPoolerSize );

	String getId() { return( id ); };
	MindRegionTypeDef *getType() { return( typeDef ); };
	int getSpatialPoolerSize() { return( spatialPoolerSize ); };
	int getTemporalPoolerSize() { return( temporalPoolerSize ); };
	bool isUsingSpatialPooler() { return( useSpatialPooler ); };
	bool isUsingTemporalPooler() { return( useTemporalPooler ); };
	int getTemporalDepth() { return( temporalDepth ); };

	void getSizeInfo( int *nx , int *ny );

private:
	String id;
	MindRegionTypeDef *typeDef;

	int sizeX;
	int sizeY;
	bool useSpatialPooler;
	bool useTemporalPooler;
	int temporalDepth;
	int spatialPoolerSize;
	int temporalPoolerSize;
};

/*#########################################################################*/
/*#########################################################################*/

class MockLink : public NeuroLink {
public:
	MockLink( String type , NeuroLinkSource *src , NeuroLinkTarget *dst );
	virtual const char *getClass() { return( "MockLink" ); };

public:
	virtual void createNeuroLink( NeuroLinkInfo *info );
	virtual NeuroSignal *apply( NeuroSignal *srcData , NeuroPool *dstPool );

private:
// utilities
	String type;
	int opid;
};

/*#########################################################################*/
/*#########################################################################*/

class ExcitatoryLink : public NeuroLink {
public:
	ExcitatoryLink( NeuroLinkSource *src , NeuroLinkTarget *dst );
	virtual const char *getClass() { return( "ExcitatoryLink" ); };

public:
	virtual void createNeuroLink( NeuroLinkInfo *info );
	virtual NeuroSignal *apply( NeuroSignal *srcData , NeuroPool *dstPool );

private:
	void recalculateActionPotential( NeuroSignal *srcData , NeuroPool *dstPool );
	void activateMembranePotential( NeuroSignal *srcData , NeuroPool *dstPool );

private:
	int opid;
};

/*#########################################################################*/
/*#########################################################################*/

class InhibitoryLink : public NeuroLink {
public:
	InhibitoryLink( NeuroLinkSource *src , NeuroLinkTarget *dst );
	virtual const char *getClass() { return( "InhibitoryLink" ); };

public:
	virtual void createNeuroLink( NeuroLinkInfo *info );
	virtual NeuroSignal *apply( NeuroSignal *srcData , NeuroPool *dstPool );

private:
	int opid;
};

/*#########################################################################*/
/*#########################################################################*/

class ModulatoryLink : public NeuroLink {
public:
	ModulatoryLink( NeuroLinkSource *src , NeuroLinkTarget *dst );
	virtual const char *getClass() { return( "ModulatoryLink" ); };

public:
	virtual void createNeuroLink( NeuroLinkInfo *info );
	virtual NeuroSignal *apply( NeuroSignal *srcData , NeuroPool *dstPool );
};

/*#########################################################################*/
/*#########################################################################*/

#endif // INCLUDE_AH_MIND_IMPL_H
